package com.fingard.dsp.bank.directbank.cmb01;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fingard.FGBiz;
import com.fingard.constant.Format;
import com.fingard.crypto.DigestHelper;
import com.fingard.dsp.bank.directConfig.ActSetItem;
import com.fingard.dsp.bank.directbank.bankInterface.IAuthorizeForRec;
import com.fingard.dsp.bank.directbank.cmb01.util.DESUtils;
import com.fingard.dsp.bank.reqrespobj.authforrec.*;
import com.fingard.dsp.bank.reqrespobj.authforrec.detail.RetAtsQryAuthForRecDetail;
import com.fingard.io.FileHelper;
import com.fingard.text.StringHelper;
import com.fingard.xml.XmlTextReader;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.net.URLEncoder;
import java.util.Date;

public class CMB01AuthorizeForRec extends CMB01Base implements IAuthorizeForRec {
    @Override
    public RetAtsAuthForRec d_auth(ReqAuthForRec p_req) throws Exception {
        boolean newVersion = getBankConfig().getValueAsBool("AuthNewVersion");
        return newVersion ? d_auth_Protocol(p_req) : d_auth_Old(p_req);
    }

    public RetAtsAuthForRec d_auth_Old(ReqAuthForRec p_req) throws Exception {
        RetAtsAuthForRec retAts = new RetAtsAuthForRec(p_req.reqHeader);

        try {
            String merchatId = getBankConfig().getMapValueByKey("contractInfoMapping", "merchatId");
            String mouldNo = getBankConfig().getMapValueByKey("contractInfoMapping", "mouldNo");
            String chargeBasis = "";
            String jumpUrl = getBankConfig().getMapValueByKey("contractInfoMapping", "jumpUrl");
            String properUrl = getBankConfig().getMapValueByKey("contractInfoMapping", "properUrl");
            String desEncryptKey = getBankConfig().getMapValueByKey("contractInfoMapping", "desEncryptKey");

            StringBuilder signBuilder = new StringBuilder();
            signBuilder.append(merchatId);
            signBuilder.append(mouldNo);
            signBuilder.append(chargeBasis);
            signBuilder.append(jumpUrl);
            signBuilder.append(properUrl);

            String waitSignStr = signBuilder.toString();
            WriteBankLogLn2("签名原始数据:\r\n" + waitSignStr);
            System.out.println("签名原始数据:\r\n" + waitSignStr);

            String md5Str = DigestHelper.cryptoMD5RetHexStr(waitSignStr.getBytes("UTF-8")).toUpperCase();
            WriteBankLogLn2("MD5值:" + md5Str);
            System.out.println("MD5值:" + md5Str);

            String desStr = DESUtils.encode(md5Str, desEncryptKey);
            WriteBankLogLn2("DES值:" + desStr);
            System.out.println("DES值:" + desStr);

            StringBuilder tmpReqStr = new StringBuilder();
            tmpReqStr.append(bankFront.getUrl("contract"));
            tmpReqStr.append("&MerchantNum=").append(merchatId);
            tmpReqStr.append("&TemplateNum=").append(mouldNo);
            tmpReqStr.append("&ChargeBasis=").append("");
            String encodeJumpUrl = URLEncoder.encode(URLEncoder.encode(jumpUrl, "UTF-8"), "UTF-8");
            System.out.println("encodeJumpUrl:" + encodeJumpUrl);
            tmpReqStr.append("&JumpUrl=").append(encodeJumpUrl);
            String encodePropelUrl = URLEncoder.encode(URLEncoder.encode(properUrl, "UTF-8"), "UTF-8");
            System.out.println("encodePropelUrl:" + encodePropelUrl);
            tmpReqStr.append("&PropelUrl=").append(encodePropelUrl);
            tmpReqStr.append("&Signature=").append(desStr);

            WriteBankLogLn2("发送银行请求数据:\r\n" + tmpReqStr.toString());
            System.out.println("发送银行请求数据:\r\n" + tmpReqStr.toString());

            String tmpQRCodePath = FGBiz.dspCenter.rootDirPath + File.separator + "config" + File.separator + "portfiles" + File.separator + "CMB01" + File.separator + "QRCode.txt";
            System.out.println("请求二维码链接地址保存本地路径:\r\n" + tmpQRCodePath);
            FileHelper.writeFile(tmpQRCodePath, tmpReqStr.toString(), "UTF-8");
            WriteBankLogLn2("地址保存成功...");

            retAts.respCode = "0";
            retAts.respInfo = "签约链接生成成功";
        } catch (Exception ex) {
            ex.printStackTrace();
            retAts.respCode = "-1";
            retAts.respInfo = ex.getMessage();
            WriteBankLogLn(ex);
        }

        retAts.writeRetToATS();
        return retAts;
    }

    public RetAtsAuthForRec d_auth_Protocol(ReqAuthForRec p_req) throws Exception {
        RetAtsAuthForRec retAts = new RetAtsAuthForRec(p_req.reqHeader);
        try {
            ActSetItem actItem = getBankConfig().getActSetItem(p_req.ownAct, "auth");
            if (actItem == null) {
                retAts.respCode = "-1";
                retAts.respInfo = "未找到账号[" + p_req.ownAct + "]相应商户配置信息!";
                retAts.writeRetToATS();
                return retAts;
            }

            StringBuilder reader_str = new StringBuilder();
            reader_str.append("<ATSYH><TransResp><BankCode>CMB01</BankCode>");
            reader_str.append("<TransType>QENDIIMPT</TransType>");
            reader_str.append("<TransSeqID></TransSeqID>");
            reader_str.append("<TransParam>");
            reader_str.append("<ReqSeqID>" + p_req.reqSeqID + "</ReqSeqID>");
            reader_str.append("<RespCode></RespCode>");
            reader_str.append("<RespInfo></RespInfo>");
            reader_str.append("<ResultType></ResultType>");
            reader_str.append("<TransState></TransState>");
            reader_str.append("<PayInfoCode></PayInfoCode>");
            reader_str.append("<ReconcilyNo></ReconcilyNo>");

            retAts.respCode = "0";
            retAts.reqSeqID = p_req.reqSeqID;

            while (p_req.readRecord()) {
                JSONObject tmpJsonRequest = new JSONObject();
                JSONObject tmpReqHeader = new JSONObject();
                tmpReqHeader.put("xDevNbr", "");
                tmpReqHeader.put("xMacCod", "");
                tmpReqHeader.put("xTlrNbr", "");
                tmpReqHeader.put("xCmmTyp", "");
                tmpReqHeader.put("xEncCod", "");
                tmpReqHeader.put("xIsuDat", "");
                tmpReqHeader.put("xAppRsv", "");
                tmpReqHeader.put("xOrgIsu", "");
                tmpReqHeader.put("xDskSys", "");
                tmpReqHeader.put("xRtnLvl", "");
                tmpReqHeader.put("xPreIsu", "");
                tmpReqHeader.put("xTypCod", "");
                tmpReqHeader.put("xIsuCnl", "");
                tmpReqHeader.put("xEntUsr", "");
                tmpReqHeader.put("xKeyVal", "");
                tmpReqHeader.put("xRtnCod", "");
                tmpReqHeader.put("xHdrLen", "");
                tmpReqHeader.put("xDocSiz", "");
                tmpReqHeader.put("xSysCod", "");
                tmpReqHeader.put("xCmmRsv", "");
                tmpReqHeader.put("xUsrPwd", "");
                tmpReqHeader.put("xItvTms", "");
                tmpReqHeader.put("xDalCod", "");
                tmpReqHeader.put("xIsuTim", "");
                tmpReqHeader.put("xRqsNbr", "");
                tmpReqHeader.put("xWkeCod", "AKACNCMV");
                tmpReqHeader.put("xMsgFlg", "");
                tmpReqHeader.put("xUsrDta", "");
                tmpReqHeader.put("xUsrTok", "");
                tmpReqHeader.put("xReqSrc", "");
                tmpJsonRequest.put("HEAD", tmpReqHeader);

                JSONArray jsonDetailArray = new JSONArray();

                JSONObject tmpDetailParams = new JSONObject();
                tmpDetailParams.put("xCprSeq", p_req.reqSeqID);//商户流水
                tmpDetailParams.put("xCprNbr", actItem.merchantId);//商户编码
                tmpDetailParams.put("xCprDat", Format.Date8Format.format(new Date()));//商户日期
                tmpDetailParams.put("xCprTim", Format.Time6Format.format(new Date()));//商户时间
                tmpDetailParams.put("xEacNam", p_req.readedDetail.oppActName);//客户姓名
                tmpDetailParams.put("xEacNbr", p_req.readedDetail.oppAct);//客户银行卡号
                tmpDetailParams.put("xCtfTyp", "P01");//客户证件类型
                tmpDetailParams.put("xCtfNbr", p_req.readedDetail.certNum);//客户证件号码
                tmpDetailParams.put("xMobTel", p_req.readedDetail.cellPhone);//客户预留手机号
                tmpDetailParams.put("xCprAct", p_req.readedDetail.sourceNoteCode);//扣款依据
                String xSglAmt = getBankConfig().getMapValueByKey("contractKeyMapping", "singleLimit");
                if (StringHelper.isNullOrEmpty(xSglAmt)) {
                    WriteBankLogLn(p_req.reqSeqID + ":缺失配置节点'singleLimit'或值为空!");
                }
                tmpDetailParams.put("xSglAmt", xSglAmt);//单笔限额
                String xPerAmt = getBankConfig().getMapValueByKey("contractKeyMapping", "monthAmtLimit");
                if (StringHelper.isNullOrEmpty(xPerAmt)) {
                    WriteBankLogLn(p_req.reqSeqID + ":缺失配置节点'monthAmtLimit'或值为空!");
                }
                tmpDetailParams.put("xPerAmt", xPerAmt);//周期限额
                String xEftTer = getBankConfig().getMapValueByKey("contractKeyMapping", "deadLine");
                if (StringHelper.isNullOrEmpty(xEftTer)) {
                    WriteBankLogLn(p_req.reqSeqID + ":缺失配置节点'deadLine'或值为空!");
                }
                tmpDetailParams.put("xEftTer", xEftTer);//协议有效期
                tmpDetailParams.put("xSpc100", p_req.reqSeqID);//备注信息
                jsonDetailArray.add(tmpDetailParams);

                JSONObject jsonArray = new JSONObject();
                jsonArray.put("AKACNCMVX1", jsonDetailArray);
                tmpJsonRequest.put("BODY", jsonArray);
                String appid = getBankConfig().getValueAsString("appId");
                String appSecret = getBankConfig().getValueAsString("appSecret");
                WriteBankLogStep2(tmpJsonRequest.toJSONString());

                String tmpStrRet[] = sendToBank(tmpJsonRequest, appid, appSecret, bankFront.getUrl("authProtocol"));

                String transState = "";
                String payinfocode = "";
                String payinfo = "";

                if (tmpStrRet[0].length() == 0) {
                    JSONObject tmpRespJson = JSONObject.parseObject(tmpStrRet[1]);
                    JSONObject tmpRespHeadJson = tmpRespJson.getJSONObject("HEAD");
                    if (tmpRespHeadJson != null) {
                        String tmpReturnCode = tmpRespHeadJson.getString("xRtnCod");
                        JSONObject tmpRespBodyJson = tmpRespJson.getJSONObject("BODY");
                        if ("SUC0000".equalsIgnoreCase(tmpReturnCode) || "AKA0458".equalsIgnoreCase(tmpReturnCode)) {
                            transState = "2";
                            payinfo = tmpReturnCode;
                        } else {
                            transState = "3";
                            JSONArray jsonErrMsg = tmpRespBodyJson.getJSONArray("$ERRORMSG$");
                            String errMsg = jsonErrMsg.getJSONObject(0).getString("xErrMsg");
                            String[] errMsgArray = errMsg.split("-");
                            if (errMsgArray!= null && errMsgArray.length==2) {
                                payinfocode = errMsgArray[0].trim();
                                payinfo = errMsgArray[1].trim();
                            } else {
                                payinfo = errMsg;
                            }
                        }
                        JSONArray reqseq = tmpRespBodyJson.getJSONArray("$REQSEQ$");
                        if (reqseq != null) {
                            retAts.serialNo = reqseq.getJSONObject(0).getString("xReqSeq");
                        }
                    }
                }

                reader_str.append("<DetailRecord>");
                reader_str.append("<AuthCode>" + p_req.readedDetail.authCode + "</AuthCode>");
                reader_str.append("<ISeqno>" + p_req.readedDetail.authCode + "</ISeqno>");
                reader_str.append("<PayCode>" + payinfocode + "</PayCode>");
                reader_str.append("<PayInfo>" + payinfo + "</PayInfo>");
                reader_str.append("<ContractNo></ContractNo>");
                reader_str.append("<PayType></PayType>");
                reader_str.append("<PayAcctName>" + p_req.readedDetail.oppActName + "</PayAcctName>");
                reader_str.append("<PayAcctNo>" + p_req.readedDetail.oppAct + "</PayAcctNo>");
                reader_str.append("<DeadLine></DeadLine>");
                reader_str.append("<TransState>" + transState + "</TransState>");
                reader_str.append("</DetailRecord>");
            }
            reader_str.append("</TransParam></TransResp></ATSYH>");
            String tmpLocalMarkPath = getTempFileDirectory() + File.separator + p_req.reqSeqID + ".txt";
            WriteBankLogLn2("批次授权明细结果文件路径: " + tmpLocalMarkPath);
            FileHelper.writeFile(tmpLocalMarkPath, reader_str.toString(), getCharset());
        } catch (Exception ex) {
            ex.printStackTrace();
            retAts.respCode = "-1";
            retAts.respInfo = ex.getMessage();
            WriteBankLogLn(ex);
        }

        retAts.writeRetToATS();
        return retAts;
    }

    @Override
    public RetAtsQryAuthForRec d_qry_auth(ReqQryAuthForRec p_req) throws Exception {
        RetAtsQryAuthForRec retAts = new RetAtsQryAuthForRec(p_req.reqHeader);
        retAts.writeStart();

        FileReader reader = null;
        BufferedReader br = null;

        try {
            String tmpFilePath = getTempFileDirectory() + File.separator + p_req.reqSeqID + ".txt";
            File tmpFile = new File(tmpFilePath);
            if (!tmpFile.exists()) {
                retAts.respCode = "0";
                retAts.respInfo = "未授权";
                retAts.transState = "4";
            } else {
                retAts.respCode = "0";
                String resultMsg = FileHelper.readFileText(tmpFilePath, getCharset());
                WriteBankLogLn("授权结果内容：" + resultMsg);
                StringBuilder tmpSbMsg = new StringBuilder();
                XmlTextReader tmpBkReader = loadBankRespXmlReader(resultMsg, tmpSbMsg);
                while (tmpBkReader.read("/ATSYH/TransResp/TransParam/DetailRecord")) {
                    RetAtsQryAuthForRecDetail tmpRetDetail = new RetAtsQryAuthForRecDetail();
                    tmpRetDetail.authCode = tmpBkReader.readedXElement.getSingleText("AuthCode");
                    tmpRetDetail.iSeqno = tmpBkReader.readedXElement.getSingleText("ISeqno");
                    tmpRetDetail.payInfo = tmpBkReader.readedXElement.getSingleText("PayInfo");
                    tmpRetDetail.payCode = tmpBkReader.readedXElement.getSingleText("PayCode");
                    tmpRetDetail.contractNo = tmpBkReader.readedXElement.getSingleText("ContractNo");
                    tmpRetDetail.payType = tmpBkReader.readedXElement.getSingleText("PayType");
                    tmpRetDetail.oppActName = tmpBkReader.readedXElement.getSingleText("PayAcctName");
                    tmpRetDetail.oppAct = tmpBkReader.readedXElement.getSingleText("PayAcctNo");
                    tmpRetDetail.deadLine = tmpBkReader.readedXElement.getSingleText("DealLine");
                    tmpRetDetail.transState = tmpBkReader.readedXElement.getSingleText("TransState");
                    retAts.writeRetDetail(tmpRetDetail);
                }
            }
        } catch (Exception ex) {
            ex.printStackTrace();
            retAts.respCode = "-1";
            retAts.respInfo = ex.getMessage();
            WriteBankLogLn(ex);
        } finally {
            if (reader != null) {
                reader.close();
            }
            if (br != null) {
                br.close();
            }
        }

        retAts.writeAfterDetail();
        return retAts;
    }

    @Override
    public RetAtsQryRecAuthInfo d_qry_authInfo(ReqQryRecAuthInfo p_req) throws Exception {
        return null;
    }
}